/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
 */

#ifndef _NET_BOND_SLB_H
#define _NET_BOND_SLB_H

#define BOND_MODE_SLB                               7
static inline bool should_fail_over_mac(int mode)
{
#ifdef CONFIG_VENDOR_BONDING_SLB_HOOKS
	return mode != BOND_MODE_SLB;
#else
	return true;
#endif
}
#ifdef CONFIG_VENDOR_BONDING_SLB_HOOKS

#include <linux/kernel.h>
#include <linux/if_bonding.h>

#define BOND_LINK_ARP_INTERV                        0
#define SLB_SLOT_SIZE                               30
#define SLB_NULL_INDEX                              0xffffffff
#define ETH_MAC_CHASSIS_INDEX                       3
#define ETH_MAC_SLOT_INDEX                          4
#define ETH_IP_CHASSIS_INDEX                        2
#define ETH_IP_SLOT_INDEX                           3
#define SLB_HASH_TABLE_SIZE                         16
#define BOND_SLB_MC_GROUP_ID_MAX                    7
#define BOND_SLB_MC_GROUP_ID_DEFAULT                6
#define BOND_SLB_ARP_STALE_TIME_DEFAULT             20000
#define BOND_SLB_LOGMSG_MAX_LEN                     256
#define IP_BUFFER_SIZE                              4

struct slb_arp_request_info {
	__be32 ip_dst;
	struct hlist_node ar_list;
	u8 mac_dst[ETH_ALEN];
	u8 assigned_by_self;
	u8 assigned_by_peer;
	struct slave *slave;
	unsigned long last_tx_ip;
	unsigned long last_rx;
};

struct slb_bond_info {
	struct list_head next_slb_info;
	struct hlist_head *arp_request_hashtbl;
	long arp_request_count;
	spinlock_t arp_request_hashtbl_lock;
	struct packet_type slb_pkt_type;
	struct delayed_work slb_work;
	struct bonding *bond;
	int own_chassis;
	int own_slot;
};

struct slb_arp_pkt {
	__be16  hw_addr_space;
	__be16  prot_addr_space;
	u8      hw_addr_len;
	u8      prot_addr_len;
	__be16  op_code;
	u8      mac_src[ETH_ALEN];
	__be32  ip_src;
	u8      mac_dst[ETH_ALEN];
	__be32  ip_dst;
} __packed;

#define BOND_SLB_PRINTF(fmt, args...) pr_info("[info][bond slb]"fmt"\n", ##args)
#define BOND_SLB_ERR_PRINTF(fmt, args...) pr_err("[err ][bond slb]"fmt"\n", ##args)
#define BOND_SLB_DBG_PRINTF(fmt, args...)                                   \
	do {                                                                    \
		if (bond_slb_is_debug()) {                                   \
			pr_debug("[dbg ][bond slb]"fmt"\n", ##args);   \
		}                                                                   \
	} while (0)

static inline struct slb_arp_pkt *slb_get_arp_pkt(const struct sk_buff *skb)
{
	return (struct slb_arp_pkt *)skb_network_header(skb);
}
void bond_slb_open(struct bonding *bond, struct net_device *bond_dev);
void bond_slb_close(struct bonding *bond);
netdev_tx_t bond_slb_xmit(struct sk_buff *skb, struct net_device *bond_dev);
struct slave *bond_slb_xmit_slave_get(struct bonding *bond, struct sk_buff *skb);
void bond_slb_release_slave(struct bonding *bond, struct net_device *slave_dev);
int bond_slb_slave_event_change(struct bonding *bond, struct net_device *slave_dev);
void bond_slb_enslave(struct bonding *bond, struct slave *new_slave);
void bond_slb_procfs_show_arp(struct bonding *bond, struct seq_file *seq);
struct slb_arp_request_info *bond_slb_find_arp_req(struct slb_bond_info *bond_info,
							 __be32 ip_addr, int add);
int bond_slb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev,
					  struct packet_type *ptype, struct net_device *orig_dev);
void bond_slb_del_arp_req(struct bonding *bond, struct slb_bond_info *slb_info,
						  struct slb_arp_request_info *arp_req);
void bond_slb_arp_mon(struct work_struct *work);
int bond_slb_init_arp_hashtbl(struct bonding *bond, struct slb_bond_info *slb_info);
void bond_slb_deinit_arp_hashtbl(struct bonding *bond, struct slb_bond_info *slb_info);
void bond_slb_send_arp_all_slave(struct bonding *bond, __be32 ip_addr);
void bond_slb_print_arppkt(struct slb_arp_pkt *arp);
void bond_slb_procfs_show_arp(struct bonding *bond, struct seq_file *seq);
int bond_slb_get_mac_multicast(unsigned char *mac_addr, unsigned int len);
bool bond_slb_is_mac_multicast(unsigned char *mac_addr, unsigned int len);
int bond_slb_get_arp_stale_time(void);
void bond_slb_check_params(void);
int bond_slb_get_debug_level(void);
void bond_slb_info_list_init(void);
struct slb_bond_info *bond_slb_info_get(struct bonding *bond);

#endif
#endif /* _NET_BOND_SLB_H */

